package hc.bre

import static org.junit.jupiter.api.Assertions.*

import java.sql.Statement

import org.junit.jupiter.api.*
import hc.bre.data.setting.*

@groovy.transform.CompileStatic
class SettingTest {
	@Test
	void create() {
		SettingItem item = new SettingItem();

		item = new SettingItem().load([id:1,value:2]);

		assert item.value == 2;

		item = new SettingItem().load(
				[id:1,code:'v1',type:'object',
					list:[[id:11,code:'v11',value:11], [id:12,code:'v12',value:'12'],],]);

		assert item.list.size() ==2;
		assert item.list[0].value ==11;
		assert item.list[1].value =='12';
	}

	static String jsonText = '''
{
  "rid": 258,
  "rtype": "data:setting",
  "rname": null,
  "rpath": "test/Setting",
  "rversion": 0,
  "rtdata": null,
  "rmemo": "",
  "rtest": "{}",
  "rmaxid": 1,
  "list": [
    {
      "id": 1,
      "code": "arg1",
      "name": "参数1",
      "value": "数值1",
      "type": "text"
    },    
	{
      "id": 1,
      "code": "arg2",
      "name": "参数2",
      "value": 2,
      "type": "number"
    }
  ]
}
'''

	@Test
	void load() {
		SettingDefinition ruleDef = new SettingDefinition();
		ruleDef.load(hc.Util.jsonRead(jsonText));
		assert ruleDef.list.size() == 2;

		ruleDef = (SettingDefinition) new SettingDefinition().load(hc.Util.jsonRead(jsonText) as Map);
		assert ruleDef.list[0]['id'] == 1;
		assert ruleDef.list[0]['code'] == 'arg1';
		assert ruleDef.list[0]['name'] == '参数1';
		assert ruleDef.list[0]['value'] == '数值1';
		assert ruleDef.list[0]['type'] == 'text';

		assert ruleDef.list[1]['value'] == 2;
	}

	@Test
	void buildAndCompile() {
		SettingDefinition ruleDef = new SettingDefinition();
		ruleDef.load(hc.Util.jsonRead(jsonText));
		Class clazz= ruleDef.buildRuleClass(null)
		assert clazz.getName() =='test.Setting';
		assert clazz.getField('arg1').get(clazz) =='数值1';
		assert clazz.getField('arg2').get(clazz) == 2;
	}

	@Test
	void buildScriptsOfObject() {
		String jsonText = '''
{
    "rid": 258,
    "rtype": "data:setting",
    "rname": null,
    "rpath": "test/Setting",
    "rversion": 0,
    "rtdata": null,
    "rmemo": "",
    "rtest": "{}",
    "rmaxid": 5,
    "list": [
        {
            "id": 1,
            "code": "complex",
            "name": "参数1",
            "value": "",
            "type": "object",
            "list": [
                {
                    "id": 2,
                    "code": "prop1",
                    "name": "shuxing1",
                    "type": "number",
                    "value": "1024"
                },
                {
                    "id": 3,
                    "code": "prop2",
                    "name": "shuxing2",
                    "type": "text",
                    "value": "wenbenzhi2"
                },
                {
                    "id": 4,
                    "code": "prop3",
                    "name": "shuxing3",
                    "type": "object",
                    "value": "",
                    "list": [
                        {
                            "id": 5,
                            "code": "prop31",
                            "name": "shuxing31",
                            "type": "text",
                            "value": "wenbenzhi31"
                        }
                    ]
                }
            ]
        }
    ]
}
'''
		SettingDefinition ruleDef = new SettingDefinition();
		ruleDef.load(hc.Util.jsonRead(jsonText));
		Class clazz= ruleDef.buildRuleClass()
		def complex = clazz.getField('complex').get(clazz) ;
		assert complex instanceof Map;
		assert complex['prop1'] == 1024;
		assert complex['prop3'] instanceof Map;
		assert complex['prop3']['prop31'] == 'wenbenzhi31';
	}

	@Test
	void buildScriptsOfCustomerObject() {
		String jsonText = '''
{
    "rid": 258,
    "rtype": "data:setting",
    "rname": null,
    "rpath": "test/Setting",
    "rversion": 0,
    "rtdata": null,
    "rmemo": "",
    "rtest": "{}",
    "rmaxid": 5,
    "list": [
        {
            "id": 1,
            "code": "datasource",
            "name": "fanqizhashujuyuan",
            "value": "org.springframework.jdbc.datasource.DriverManagerDataSource",
            "type": "object",
            "list": [
                {
                    "id": 2,
                    "code": "url",
                    "name": "",
                    "type": "text",
                    "value": "jdbc:h2:mem:testdb;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"
                },
                {
                    "id": 3,
                    "code": "username",
                    "name": "username",
                    "type": "text",
                    "value": "root"
                },
                {
                    "id": 4,
                    "code": "password",
                    "name": "password",
                    "type": "text",
                    "value": "root"
                }
            ]
        }
    ]
}
'''
		SettingDefinition ruleDef = new SettingDefinition();
		ruleDef.load(hc.Util.jsonRead(jsonText));

		Class clazz= ruleDef.buildRuleClass()
		assert clazz.getName() =='test.Setting';
		def datasource = clazz.getField('datasource').get(clazz);
		assert datasource instanceof org.springframework.jdbc.datasource.DriverManagerDataSource

		org.springframework.jdbc.core.JdbcTemplate jdbcTemplate = new org.springframework.jdbc.core.JdbcTemplate();
		jdbcTemplate.dataSource =datasource;
		def list = jdbcTemplate.queryForList("select * from user");
		
		println hc.Util.jsonWrite(list);
	}

	@Test
	void buildScriptsOfJdbcTemplate() {
		String jsonText ='''
	{
	"rid": 258,
	"rtype": "data:setting",
	"rname": null,
	"rpath": "xsxdjc/Setting",
	"rversion": 11,
	"rtdata": null,
	"rmemo": "",
	"rtest": "{}",
	"rmaxid": 15,
	"list": [
	  {
		"id": 1,
		"code": "jdbcTemplate",
		"name": "JdbcTemple for SQL Query",
		"type": "object",
		"value": "org.springframework.jdbc.core.JdbcTemplate",
		"list": [
		  {
			"id": 11,
			"code": "dataSource",
			"name": "DataSource for Jdbc Template",
			"type": "object",
			"value": "org.springframework.jdbc.datasource.DriverManagerDataSource",
			"list": [
			  {
				"id": 13,
				"code": "url",
				"name": "",
				"type": "text",
				"value": "jdbc:h2:mem:testdb;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE",
				"list": null
			  },
			  {
				"id": 14,
				"code": "username",
				"name": "",
				"type": "text",
				"value": "root",
				"list": null
			  },
			  {
				"id": 15,
				"code": "password",
				"name": "",
				"type": "text",
				"value": "root",
				"list": null
			  }
			]
		  }
		]
	  }
	]
  }
'''
		SettingDefinition ruleDef = new SettingDefinition();
		ruleDef.load(hc.Util.jsonRead(jsonText));
		Class clazz= ruleDef.buildRuleClass()

		def jdbcTemplate = clazz.getField('jdbcTemplate').get(clazz);
		assert jdbcTemplate instanceof org.springframework.jdbc.core.JdbcTemplate
		
		//		def list = jdbcTemplate.queryForList("select * from user");
		//		println hc.Util.jsonWrite(list);
	}

	@Test
	void buildTest() {
		String script ="""
package xsxdjc

class Setting {
	 public static final org.springframework.jdbc.datasource.DriverManagerDataSource dataSource;
	 static {
		 dataSource = Class.forName('org.springframework.jdbc.datasource.DriverManagerDataSource').getConstructor(null).newInstance();
		 dataSource.url = '''jdbc:h2:mem:testdb;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE''';
		 dataSource.username = '''root''';
		 dataSource.password = '''root''';
	 }
	 public static final org.springframework.jdbc.core.JdbcTemplate jdbcTemplate;
	 static {
		 jdbcTemplate = Class.forName('org.springframework.jdbc.core.JdbcTemplate').getConstructor().newInstance();
		 jdbcTemplate.dataSource = dataSource
	 };
}
"""
		def codeSource = new GroovyCodeSource(script,
				"Setting",
				System.getProperty("java.io.tmpdir"))

		GroovyClassLoader classLoader =
				new GroovyClassLoader(Thread.currentThread().getContextClassLoader());

		Class clazz = classLoader.parseClass(codeSource);

		org.springframework.jdbc.core.JdbcTemplate jdbcTemplate = clazz.getField('jdbcTemplate').get(clazz) as org.springframework.jdbc.core.JdbcTemplate;

		def list = jdbcTemplate.queryForList("select * from user");
		
//		println hc.Util.jsonWrite(list);
	}

	@Test
	void buildTest2() {
		String script ="""

package xsxdjc

class Setting {
		
	 public static final org.springframework.jdbc.core.JdbcTemplate jdbcTemplate;

	 static {
		 jdbcTemplate = Class.forName('org.springframework.jdbc.core.JdbcTemplate').getConstructor().newInstance();
		 jdbcTemplate.dataSource = 
		 (
			 {
				org.springframework.jdbc.datasource.DriverManagerDataSource dataSource;
				dataSource = Class.forName('org.springframework.jdbc.datasource.DriverManagerDataSource').getConstructor(null).newInstance();
		 		dataSource.url = '''jdbc:h2:mem:testdb;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE''';
		 		dataSource.username = '''root''';
		 		dataSource.password = '''root''';
		 		return dataSource;
			}
		).call();
	 };
}
"""
		def codeSource = new GroovyCodeSource(script,
				"Setting",
				System.getProperty("java.io.tmpdir"))

		GroovyClassLoader classLoader =
				new GroovyClassLoader(Thread.currentThread().getContextClassLoader());

		Class clazz = classLoader.parseClass(codeSource);

		org.springframework.jdbc.core.JdbcTemplate jdbcTemplate = clazz.getField('jdbcTemplate').get(clazz) as org.springframework.jdbc.core.JdbcTemplate;

		def list = jdbcTemplate.queryForList("select * from user");
		
//		println hc.Util.jsonWrite(list);
	}

	@BeforeAll
	static public void buildDb() {
		DBTest.initIfNone()
	}
}
